﻿/*****************************************************************//**
 * @file    FITKGraphObjectPostBase.h
 * @brief   Post graph object base.
 *  
 * @author  ChengHaotian (yeguangbaozi@foxmail.com)
 * @date    2024-05-17
 *********************************************************************/

#ifndef __FITKGRAPHOBJECTPOSTBASE_H__
#define __FITKGRAPHOBJECTPOSTBASE_H__

#include "FITKGraphObject3D.h"

#include "FITKVTKGraphAdaptorAPI.h"
#include "FITKGraphCommons.h"

// Forward declaration
class QVariant;

class vtkDataSet;
class vtkLookupTable;
class vtkScalarBarActor;
class vtkTextActor;
class vtkVolume;
class vtkDataSetTriangleFilter;
class vtkOutlineFilter;
class vtkAlgorithmOutput;

/**
 * @brief   The scalar's hue value type.
 * @author  ChengHaotian (yeguangbaozi@foxmail.com)
 * @date    2024-05-22
 */
enum HueType
{
    BlackToWhite = 0,
    // BlueToRed,
    Rainbow,
    // RedToBlue,
    ReversedRainbow,
    WhiteToBlack
};

/**
 * @brief   The representation type.
 * @author  ChengHaotian (yeguangbaozi@foxmail.com)
 * @date    2025-01-21
 */
enum RepType
{
    Actor = 0,
    Volume
};

namespace Exchange
{
    /**
     * @brief   Post graph object base.
     * @author  ChengHaotian (yeguangbaozi@foxmail.com)
     * @date    2024-05-17
     */
    class FITKVTKGRAPHADAPTORAPI FITKGraphObjectPostBase : public FITKGraphObject3D
    {
        // Regist
        FITKGraphObjectRegist(FITKGraphObjectPostBase, FITKGraphObject3D);
        FITKCLASS(Exchange, FITKGraphObjectPostBase);

    public:
        /**
         * @brief   Constructor.
         * @param   caseData: The case data( If the post data is import with file, the case data maybe nullptr)
         * @param   dataObj: The input post data object
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-17
         */
        FITKGraphObjectPostBase(AbaqusData::FITKDataCase* caseData, Core::FITKAbstractDataObject* dataObj);

        /**
         * @brief   Destructor.[virtual]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-17
         */
        virtual ~FITKGraphObjectPostBase();

        /**
         * @brief   Set the number of color steps.[virtual]
         * @param   nSteps: The number of steps
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-22
         */
        virtual void setNumberOfColorStep(int nSteps);

        /**
         * @brief   Set the number of the scalar bar's color steps.
         * @param   nSteps: The number of steps
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-23
         */
        void setNumberOfBarColorStep(int nSteps);

        /**
         * @brief   Enable or disable the deformation.[virtual]
         * @param   isOn: Is on
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        virtual void setEnableDeform(bool isOn);

        /**
         * @brief   Change the color by the given array type, name and component name.[virtual]
         * @param   type: The array type( 0: Solid, 1: Points, 2: Cells )[quote]
         * @param   name: The name of the array[quote]
         * @param   compName: The name of the component array[quote]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        virtual void changeField(int& type, QString& name, QString& compName);

        /**
         * @brief   Change the color by the given array type, name and component name.[virtual]
         * @param   type: The array type( 0: Solid, 1: Points, 2: Cells )[quote]
         * @param   name: The name of the array[quote]
         * @param   compIndex: The index of the component array[quote]
         * @param   compName: The name of the component array[quote]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        virtual void changeField(int& type, QString& name, int& compIndex, QString& compName);

        /**
         * @brief   Set the scalar bar visiblility forcely.
         * @param   visibile
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-21
         */
        void setScalarBarVisibility(bool visibile);

        /**
         * @brief   Set the hue type of the scalar.[virtual]
         * @param   type: The hue type
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-22
         */
        virtual void setHueType(HueType type);

        /**
         * @brief   Set the scalar's color data range.[virtual]
         * @param   min: The min value
         * @param   max: The max value
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-22
         */
        virtual void setScalarRange(double min, double max);

        /**
         * @brief   Show or hide the labels of the max and min value of the coloring array.[virtual]
         * @param   visibile: The visibility.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-22
         */
        virtual void setMaxAndMinVisible(bool visibile);

        /**
         * @brief   Set the transparency for the actor.
         * @param   value: The transparency
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-24
         */
        virtual void setTransparency(double value);

        /**
         * @brief   Update the actors and scalar bar.[virtual][override]
         * @param   forceUpdate: Force update[default]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-23
         */
        virtual void update(bool forceUpdate = false) override;

        /**
         * @brief   Get the fixed sized bounds of this graph object.[virtual][override]
         * @param   The bounds size
         * @return  If the graph object has fixed sized bounds
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-29
         */
        virtual bool getFixedBounds(double* bounds) override;

        /**
         * @brief   Get the algorithm output port for calculation or visualization.[pure virtual]
         * @param   forRendering: The output type[default]
         * @return  The output port
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-22
         */
        virtual vtkAlgorithmOutput* getOutputPort(bool forRendering = false) = 0;

        /**
         * @brief   Get the algorithm output dataset for calculation or visualization.[pure virtual]
         * @param   forRendering: The output type[default]
         * @return  The output dataset
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-22
         */
        virtual vtkDataSet* getOutput(bool forRendering = false) = 0;

    protected:
        /**
         * @brief   Constructor.( For copying data )
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-17
         */
        FITKGraphObjectPostBase() = default;

        /**
         * @brief   Initialize the actor and properties.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        void initActors();

        // Protected tool functions.
        //@{
        /**
         * @brief   Update the scalar bar's visibility.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-21
         */
        void updateScalarBarVisible();

        /**
         * @brief   Change the color by the given array type, name and component name.
         * @param   actor: The actor
         * @param   type: The array type( 0: Solid, 1: Points, 2: Cells )[quote]
         * @param   name: The name of the array[quote]
         * @param   compName: The name of the component array[quote]
         * @param   range: The array data range
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        void changeField(FITKGraphActor* actor, int& type, QString& name, QString& compName, double* range);

        /**
         * @brief   Change the color by the given array type, name and component name.
         * @param   actor: The actor
         * @param   type: The array type( 0: Solid, 1: Points, 2: Cells )[quote]
         * @param   name: The name of the array[quote]
         * @param   compIndex: The index of the component array[quote]
         * @param   compName: The name of the component array[quote]
         * @param   range: The array data range
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        void changeField(FITKGraphActor* actor, int& type, QString& name, int& compIndex, QString& compName, double* range);

        /**
         * @brief   Change the color by the given array type, name and component name.
         * @param   volume: The volume
         * @param   lut: The look up table for colors
         * @param   type: The array type( 0: Solid, 1: Points, 2: Cells )[quote]
         * @param   name: The name of the array[quote]
         * @param   compName: The name of the component array[quote]
         * @param   range: The array data range
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-18
         */
        void changeField(vtkVolume* volume, vtkLookupTable* lut, int& type, QString& name,
            QString& compName, double* range);

        /**
         * @brief   Change the color by the given array type, name and component name.
         * @param   volume: The volume
         * @param   lut: The look up table for colors
         * @param   type: The array type( 0: Solid, 1: Points, 2: Cells )[quote]
         * @param   name: The name of the array[quote]
         * @param   compIndex: The index of the component array[quote]
         * @param   compName: The name of the component array[quote]
         * @param   range: The array data range
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-18
         */
        void changeField(vtkVolume* volume, vtkLookupTable* lut, int& type, QString& name,
            int& compIndex, QString& compName, double* range);

        /**
         * @brief   Get the data set in the actor.
         * @param   actor: The actor
         * @return  The data set
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        vtkDataSet* getActorDataSet(FITKGraphActor* actor);

        /**
         * @brief   Get the actor's lookup table in the mapper.
         * @param   actor: The actor
         * @return  The lookup table
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        vtkLookupTable* getActorLookupTable(FITKGraphActor* actor);

        /**
         * @brief   Get the index of the component in the array.
         * @param   actor: The actor
         * @param   type: The array type( 1: Points, 2: Cells )
         * @param   name: The array name
         * @param   compName: The component name
         * @param   nComp: The number of components[quote]
         * @return  The index of the component
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        int getComponentIndex(FITKGraphActor* actor, int type, QString name, QString compName, int& nComp);

        /**
         * @brief   Get the index of the component in the array.
         * @param   volume: The volume
         * @param   type: The array type( 1: Points, 2: Cells )
         * @param   name: The array name
         * @param   compName: The component name
         * @param   nComp: The number of components[quote]
         * @return  The index of the component
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-18
         */
        int getComponentIndex(vtkVolume* volume, int type, QString name, QString compName, int& nComp);

        /**
         * @brief   Get the index of the component in the array.
         * @param   dataSet: The data set
         * @param   type: The array type( 1: Points, 2: Cells )
         * @param   name: The array name
         * @param   compName: The component name
         * @param   nComp: The number of components[quote]
         * @return  The index of the component
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-22
         */
        int getComponentIndex(vtkDataSet* dataSet, int type, QString name, QString compName, int& nComp);

        /**
         * @brief   Set the scalar bar's labels number.
         * @param   nLabels: The number of scalar bar's labels
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-21
         */
        void setNumberOfLabels(int nLabels);

        /**
         * @brief   Set the number of color steps.
         * @param   actor: The actor
         * @param   nSteps: The number of steps[default]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        void setNumberOfColorStep(FITKGraphActor* actor, int nSteps = 255);

        /**
         * @brief   Set the data range for look up table.
         * @param   min: The min value
         * @param   max: The max value
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        void setColorDataRange(FITKGraphActor* actor, double min, double max);

        /**
         * @brief   Change the scalar's hue type.
         * @param   actor: The actor
         * @param   type: The hue type
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-22
         */
        void setHueType(FITKGraphActor* actor, HueType type);

        /**
         * @brief   Change the scalar's hue type.
         * @param   volume: The volume
         * @param   lut: The look up table for colors
         * @param   type: The hue type
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-20
         */
        void setHueType(vtkVolume* volume, vtkLookupTable* lut, HueType type);

        /**
         * @brief   Change the scalar's hue type.
         * @param   actor: The scalar bar actor
         * @param   type: The hue type
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-22
         */
        void setHueType(vtkScalarBarActor* actor, HueType type);

        /**
         * @brief   Change the scalar's hue type.
         * @param   lut: The actor's lookup table
         * @param   type: The hue type
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-22
         */
        void setHueType(vtkLookupTable* lut, HueType type);

        /**
         * @brief   Set the scalar's color data range.( Not support for now )[virtual]
         * @param   actor: The actor
         * @param   min: The min value
         * @param   max: The max value
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-22
         */
        void setScalarRange(FITKGraphActor* actor, double min, double max);

        /**
         * @brief   Set the actor color with the given color array and color.
         * @param   actor: The actor
         * @param   color: The color
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-24
         */
        void setActorColor(FITKGraphActor* actor, QColor color);
        //@}

        /**
         * @brief   Simplified the graph object if necessary.[virtual][override]
         * @param   enabled: Enabled simplified flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-21
         */
        virtual void simplified(bool enabled) override;

    private:
        /**
         * @brief   Update the scalar bar actor's size and position with the number of labels.
         *          ( For "setNumberOfLabels" and  "setNumberOfColorStep" )
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-21
         */
        void updateScalarBarSizeAndPos();

        /**
         * @brief   Update the scalar bar's information.
         * @param   title: The title name
         * @param   range: The data range
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-22
         */
        void updateScalarBarInfo(QString title, double* range);

        /**
         * @brief   Update the scalar bar's range.
         * @param   range: The data range
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-23
         */
        void updateScalarBarRange(double* range);

        /**
         * @brief   Update the scalar bar's range.
         * @param   min: The data range min
         * @param   min: The data range max
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-24
         */
        void updateScalarBarRange(double min, double max);
 
    protected:
        /**
         * @brief   The max number of the scalar bar's color and labels.[const]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-21
         */
        const int c_maxLabelAndColorNumber = 25;

        /**
         * @brief   The representation type.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-21
         */
        RepType m_repType = RepType::Actor;

        /**
         * @brief   The post data actor.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-20
         */
        FITKGraphActor* m_fActor{ nullptr };

#ifdef RENDER_VOLUME_TEST
        /**
         * @brief   The volume look up table.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-20
         */
        vtkLookupTable* m_volLut{ nullptr };

        /**
         * @brief   The post data volume.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-18
         */
        vtkVolume* m_volume{ nullptr };

        /**
         * @brief   The actor for simplified volume.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-21
         */
        FITKGraphActor* m_volSimpleActor{ nullptr };

        /**
         * @brief   The filter for rendering volume.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-18
         */
        vtkDataSetTriangleFilter* m_volFilter{ nullptr };

        /**
         * @brief   The filter for rendering simplified volume.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-21
         */
        vtkOutlineFilter* m_volOutlineFilter{ nullptr };
#endif

        /**
         * @brief   The scalar bar actor.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-21
         */
        vtkScalarBarActor* m_scalarBarActor{ nullptr };

        /**
         * @brief  文本演员
         * @author BaGuijun (baguijun@163.com)
         * @date   2024-12-03
         */
        vtkTextActor* m_textActor = nullptr;

        /**
         * @brief   The scalar bar visible flag.( Not the bar's visibility )
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-21
         */
        bool m_scalarBarVisible = true;

        /**
         * @brief   If the post graph is in field color mode.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-21
         */
        bool m_showContour = false;

        /**
         * @brief   The number of the scalar colors.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-20
         */
        int m_numColors = 12;

    };
}   // namespace Exchange

#endif // __FITKGRAPHOBJECTPOSTBASE_H__
